package com.nantian.nfcm.bms.loan.service;

import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.Predicate;

import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nantian.nfcm.bms.auth.dao.UserInfoDao;
import com.nantian.nfcm.bms.auth.dao.UserRoleDao;
import com.nantian.nfcm.bms.auth.entity.RoleInfo;
import com.nantian.nfcm.bms.auth.entity.UserInfo;
import com.nantian.nfcm.bms.loan.dao.LoanApplicationDao;
import com.nantian.nfcm.bms.loan.entity.LoanApplication;
import com.nantian.nfcm.bms.loan.entity.LoanInfo;
import com.nantian.nfcm.bms.loan.entity.LoanStat;
import com.nantian.nfcm.bms.loan.vo.LoanBean;
import com.nantian.nfcm.bms.loan.vo.MobileLoanBean;
import com.nantian.nfcm.util.ServiceException;
import com.nantian.nfcm.util.vo.GridData;
import com.nantian.nfcm.util.vo.LoginBean;

@Service
public class LoanApplicationQueryService {
    private LoanApplicationDao loanApplicationDao;
    private UserInfoDao userInfoDao;
    private UserRoleDao userRoleDao;
    
    //这部分常量用于方法体体内判断登陆用户的角色
    private static final String customerManager = "客户经理";
    private static final String submiter = "贷款上报人";
    private static final String examiner = "独立审查人";
    private static final String assigner = "贷款审查分配人";
	
    public LoanApplicationQueryService(LoanApplicationDao loanApplicationDao, UserInfoDao userInfoDao, UserRoleDao userRoleDao) {
    	
        this.loanApplicationDao = loanApplicationDao;
        this.userInfoDao = userInfoDao;
        this.userRoleDao = userRoleDao;
	}
    
   
	/**
	 * 根据条件查询所有贷款记录，提供给分配人和上报人使用的全局查询
	 * 
	 * @param page
	 * @param size
	 * @param loanBean
	 * @param loginUser
	 * @return
	 * @throws ServiceException
	 */
	public GridData<LoanBean> findAllLoanByCondition(int page, int size, LoanBean loanBean) throws ServiceException {
		Pageable pageable = new PageRequest(page, size);
		Specification<LoanApplication> specification = (root, query, criteriaBuilder) -> {
			List<Predicate> predicates = new ArrayList<>();

			// 贷款人模糊查询
			if (loanBean.getBorrowerName() != null && !loanBean.getBorrowerName().equals("")) {
				Predicate borrowerName = criteriaBuilder.like(root.get("borrowerName").as(String.class),
						"%" + loanBean.getBorrowerName() + "%");
				predicates.add(borrowerName);
			}

			// 贷款编号模糊查询
			if (loanBean.getLoanId() != null && !loanBean.getLoanId().equals("")) {
				Predicate loanId = criteriaBuilder.like(root.get("loanId").as(String.class),
						loanBean.getLoanId() + "%");
				predicates.add(loanId);
			}

			// 贷款类型查询条件
			if (loanBean.getLoanType() != null && !loanBean.getLoanType().equals("")) {
				Predicate loanType = criteriaBuilder.equal(root.get("loanType").as(String.class),
						loanBean.getLoanType());
				predicates.add(loanType);
			}

            //处理进度查询条件(这个查询条件只有登陆角色是客户经理时才有用)
            if(loanBean.getProcessStat() != null && !loanBean.getProcessStat().equals("")){
                Predicate loanType = criteriaBuilder.equal(root.get("processStat").as(String.class), loanBean.getProcessStat());
                predicates.add(loanType);
            }
			
			// 贷款上报时间范围
			String queryStartTime = loanBean.getQueryStartTime();
			String queryEndTime = loanBean.getQueryEndTime();

			if (queryStartTime != null && !queryStartTime.equals("") && queryEndTime != null
					&& !queryEndTime.equals("")) {
				Predicate queryTime = criteriaBuilder.between(root.get("pickupTime").as(String.class), queryStartTime,
						queryEndTime);
				predicates.add(queryTime);
			}

			query.where(criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])));
			return query.getRestriction();
		};

		Page<LoanApplication> loanApplicationPage = loanApplicationDao.findAll(specification, pageable);
		List<LoanApplication> LoanApplications = loanApplicationPage.getContent();
		List<LoanBean> loanBeans = new ArrayList<>();

		for (LoanApplication perApp : LoanApplications) {

			LoanBean resultRowBean = escape(perApp);

			loanBeans.add(resultRowBean);
		}
		GridData<LoanBean> gridData = new GridData<>();
		gridData.setData(loanBeans);
		gridData.setNumber(loanApplicationPage.getTotalElements());
		gridData.setPage(loanApplicationPage.getNumber());
		gridData.setTotalPage(loanApplicationPage.getTotalPages());
		return gridData;
	}
    
	/**
     * 查询需要记录审批结果的贷款
     * @param page
     * @param size
     * @param loanBean
     * @return
     * @throws ServiceException
     */
    public GridData<LoanBean> findByNeedApprove(int page, int size, LoanBean loanBean, LoginBean loginUser)
            throws ServiceException {
        Pageable pageable = new PageRequest(page, size);
        Specification<LoanApplication> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            //贷款人模糊查询
            if(loanBean.getBorrowerName() != null && !loanBean.getBorrowerName().equals("")){
                Predicate borrowerName = criteriaBuilder.like(root.get("borrowerName").as(String.class), "%" + loanBean.getBorrowerName() + "%");
                predicates.add(borrowerName);
            }
            
            //贷款编号模糊查询
            if(loanBean.getLoanId()!=null&&!loanBean.getLoanId().equals("")){
                Predicate loanId = criteriaBuilder.like(root.get("loanId").as(String.class), loanBean.getLoanId() + "%");
                predicates.add(loanId);
            }

            //贷款类型查询条件
            if(loanBean.getLoanType()!=null&&!loanBean.getLoanType().equals("")){
                Predicate loanType = criteriaBuilder.equal(root.get("loanType").as(String.class), loanBean.getLoanType());
                predicates.add(loanType);
            }
            
            //贷款上报时间范围
            String queryStartTime = loanBean.getQueryStartTime();
            String queryEndTime = loanBean.getQueryEndTime();
            
            if (queryStartTime != null && !queryStartTime.equals("") && queryEndTime != null && !queryEndTime.equals("") ) {
                Predicate queryTime = criteriaBuilder.between(root.get("pickupTime").as(String.class),queryStartTime,queryEndTime);
                predicates.add(queryTime);
            }
            
            //根据登陆角色来定义贷款的查询条件
            List<RoleInfo> roleInfos = userRoleDao.findRoleInfoByUserName(loginUser.getUserName());

            Predicate processStat = null;
            
            out:
            for (RoleInfo roleInfo : roleInfos) {
                switch (roleInfo.getRoleName()) {
                    //上报人
                    case submiter:       
                    	processStat = criteriaBuilder.equal(root.get("processStat").as(String.class), LoanStat.EXAMINE_SUCC_GEJING.getValue());
                        predicates.add(processStat);
                        break out; 
                    //分配人
                    case assigner:       
                    	Predicate processStat1 = criteriaBuilder.equal(root.get("processStat").as(String.class), LoanStat.EXAMINE_SUCC_LIANSHE.getValue());
                        
                    	Predicate processStat2 = criteriaBuilder.equal(root.get("processStat").as(String.class), LoanStat.CAN_NOT_EXAMINE.getValue());
                    	
                        predicates.add(criteriaBuilder.or(processStat1, processStat2));


                        break out;                            
                    default:
                        break;
                }
            }
            
            query.where(criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])));
            return query.getRestriction();
        };

        Page<LoanApplication> loanApplicationPage = loanApplicationDao.findAll(specification, pageable);
        List<LoanApplication> LoanApplications = loanApplicationPage.getContent();
        List<LoanBean> loanBeans = new ArrayList<>();

        for (LoanApplication perApp : LoanApplications) {
        	
        	LoanBean resultRowBean = escape(perApp);
        	
            loanBeans.add(resultRowBean);                 
        }
        GridData<LoanBean> gridData = new GridData<>();
        gridData.setData(loanBeans);
        gridData.setNumber(loanApplicationPage.getTotalElements());
        gridData.setPage(loanApplicationPage.getNumber());
        gridData.setTotalPage(loanApplicationPage.getTotalPages());
        return gridData;
    }
    
    /**
     * 贷款条件查询
     *
     * @param page
     * @param size
     * @param loanBean
     * @param loginUser
     * @return
     * @throws ServiceException
     */
    public GridData<LoanBean> findByCondition(int page, int size, LoanBean loanBean, LoginBean loginUser)
            throws ServiceException {
        Pageable pageable = new PageRequest(page, size);
        Specification<LoanApplication> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            //贷款人模糊查询
            if(loanBean.getBorrowerName() != null && !loanBean.getBorrowerName().equals("")){
                Predicate borrowerName = criteriaBuilder.like(root.get("borrowerName").as(String.class), "%" + loanBean.getBorrowerName() + "%");
                predicates.add(borrowerName);
            }
            
            //贷款编号模糊查询
            if(loanBean.getLoanId()!=null&&!loanBean.getLoanId().equals("")){
                Predicate loanId = criteriaBuilder.like(root.get("loanId").as(String.class), loanBean.getLoanId() + "%");
                predicates.add(loanId);
            }

            //贷款类型查询
            if(loanBean.getLoanType()!=null&&!loanBean.getLoanType().equals("")){
                Predicate loanType = criteriaBuilder.equal(root.get("loanType").as(String.class), loanBean.getLoanType());
                predicates.add(loanType);
            }
            
            //处理进度查询条件(这个查询条件只有登陆角色是客户经理时才有用)
            if(loanBean.getProcessStat() != null && !loanBean.getProcessStat().equals("")){
                Predicate loanType = criteriaBuilder.equal(root.get("processStat").as(String.class), loanBean.getProcessStat());
                predicates.add(loanType);
            }
            
            //贷款上报时间范围
            String queryStartTime = loanBean.getQueryStartTime();
            String queryEndTime = loanBean.getQueryEndTime();
            
            if (queryStartTime != null && !queryStartTime.equals("") && queryEndTime != null && !queryEndTime.equals("") ) {
                Predicate queryTime = criteriaBuilder.between(root.get("pickupTime").as(String.class),queryStartTime,queryEndTime);
                predicates.add(queryTime);
            }
            
            //根据登陆角色不同定义角色查询条件
            List<RoleInfo> roleInfos = userRoleDao.findRoleInfoByUserName(loginUser.getUserName());

            out:
            for (RoleInfo roleInfo : roleInfos) {
                switch (roleInfo.getRoleName()) {
                    case customerManager:
                    //查询条件带有客户经理用户名
                    	Predicate operator = criteriaBuilder.equal(root.get("operator").as(String.class), loginUser.getUserName());
                        predicates.add(operator);
                        break out;
                    //独立审查人
                    case examiner:
                    	Predicate examiner = criteriaBuilder.equal(root.get("approvalHandler").as(String.class), loginUser.getUserName());
                        predicates.add(examiner);
                        //上报人只查询等待上报的数据
                        Predicate examinerprocessStat = criteriaBuilder.equal(root.get("processStat").as(String.class), LoanStat.ASSIGNED.getValue());
                        predicates.add(examinerprocessStat);
                        break out;
                    //上报人
                    case submiter:       

                        //上报人只查询等待上报的数据
                        Predicate submiterProcessStat = criteriaBuilder.equal(root.get("processStat").as(String.class), LoanStat.WAIT.getValue());
                        predicates.add(submiterProcessStat);
                        break out; 
                    //分配人
                    case assigner:       
                        //上报人只查询等待分配和已经收到纸质资料的数据
                    	Predicate processStat1 = criteriaBuilder.equal(root.get("processStat").as(String.class), LoanStat.SUBMIT.getValue());
                        
                    	Predicate processStat2 = criteriaBuilder.equal(root.get("processStat").as(String.class), LoanStat.RECEIVED_FILES.getValue());
                    	
                        predicates.add(criteriaBuilder.or(processStat1, processStat2));
                    	
                        break out;                            
                    default:
                        break;
                }
            }


            query.where(criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])));
            return query.getRestriction();
        };

        Page<LoanApplication> loanApplicationPage = loanApplicationDao.findAll(specification, pageable);
        List<LoanApplication> LoanApplications = loanApplicationPage.getContent();
        List<LoanBean> loanBeans = new ArrayList<>();

        for (LoanApplication perApp : LoanApplications) {

        	LoanBean resultRowBean = escape(perApp);
            
            loanBeans.add(resultRowBean);                 
        }
        
        GridData<LoanBean> gridData = new GridData<>();
        gridData.setData(loanBeans);
        gridData.setNumber(loanApplicationPage.getTotalElements());
        gridData.setPage(loanApplicationPage.getNumber());
        gridData.setTotalPage(loanApplicationPage.getTotalPages());
        return gridData;
    }

    /**
     * 将以PO中数据转换成前端需要的展示数据
     * @param po
     * @return
     */
    private LoanBean escape(LoanApplication po) {
    	LoanBean resultRowBean = po2vo(po);

        ObjectMapper mapper = new ObjectMapper();
        // 贷款明细对象
        LoanInfo loanInfo = null;
        try {
            loanInfo = mapper.readValue(po.getDetail(), LoanInfo.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 获取贷款类型
        String typeName = "";
        switch (loanInfo.getBusinessTypes()) {
        case "1":
            typeName = "一手房贷款";
            break;
        case "2":
            typeName = "二手房贷款";
            break;
        case "3":
            typeName = "个人消费贷款";
            break;
        case "4":
            typeName = "个人经营性贷款";
            break;
        case "5":
            typeName = "农户小额信用贷款";
            break;

        }
        resultRowBean.setLoanType(typeName);

        // 获取贷款金额
        NumberFormat nf = new DecimalFormat("#,###.#### 万元");
        Double d = Double.valueOf(loanInfo.getAmount());
        String formatStr = nf.format(d);
        resultRowBean.setLoanAmount(formatStr);
        // 获取贷款周期
        resultRowBean.setLoanTerm(loanInfo.getTerm() + "个月");
        //转义当前进度处理人
        UserInfo perUser = new UserInfo();
        if (resultRowBean.getCurProcessHandler() != null
                && !resultRowBean.getCurProcessHandler().equals("")
                && !resultRowBean.getCurProcessHandler().equals("-")) {
            perUser = userInfoDao.findOne(resultRowBean.getCurProcessHandler());
            resultRowBean.setCurProcessHandler(perUser.getRealName());
        }

        //转义客户经理
        if (resultRowBean.getOperator() != null
                && !resultRowBean.getOperator().equals("")
                && !resultRowBean.getOperator().equals("-")) {
            perUser = userInfoDao.findOne(resultRowBean.getOperator());
            if (perUser != null) {
            	resultRowBean.setOperator(perUser.getRealName());
			}
        }

        //转义上报人
        if (resultRowBean.getSubmiteHandler() != null
                && !resultRowBean.getSubmiteHandler().equals("")
                && !resultRowBean.getSubmiteHandler().equals("-")) {
            perUser = userInfoDao.findOne(resultRowBean.getSubmiteHandler());
            if (perUser != null) {
            	resultRowBean.setSubmiteHandler(perUser.getRealName());
            }
            
        }

        //转义分配人
        if (resultRowBean.getAssigner() != null
                && !resultRowBean.getAssigner().equals("")
                && !resultRowBean.getAssigner().equals("-")) {
            perUser = userInfoDao.findOne(resultRowBean.getAssigner());
            
            if (perUser != null) {
            	resultRowBean.setAssigner(perUser.getRealName());
            }
            
        }

        //转义审查人
        if (resultRowBean.getApprovalHandler() != null
                && !resultRowBean.getApprovalHandler().equals("")
                && !resultRowBean.getApprovalHandler().equals("-")) {
            perUser = userInfoDao.findOne(resultRowBean.getApprovalHandler());
            
            if (perUser != null) {
            	resultRowBean.setApprovalHandler(perUser.getRealName());
            }
            
        }
        
        //判断批复是否过长
        if (resultRowBean.getCurProcessFeedback() != null && resultRowBean.getCurProcessFeedback().length() > 10) {
        	String summery = resultRowBean.getCurProcessFeedback().substring(0, 10);
        	summery += "...";
        	resultRowBean.setCurProcessFeedback(summery);
		}

        //转义贷款状态
        resultRowBean.setProcessStat(LoanStat.Helper.findCnValue(resultRowBean.getProcessStat()));
    
        //设置贷款人姓名
        resultRowBean.setBorrowerName(loanInfo.getBorrowerName());
        
        return resultRowBean;
    }
    
	
    public LoanBean findById(String loanId) throws ServiceException {
        LoanApplication loanApplication = loanApplicationDao.findOne(loanId);
        LoanBean loanBean = po2vo(loanApplication);
        ObjectMapper mapper = new ObjectMapper();
        try {
            LoanInfo loanInfo = mapper.readValue(loanApplication.getDetail(), LoanInfo.class);
            loanBean.setLoanInfo(loanInfo);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return loanBean;
    }
    
    private LoanBean po2vo(LoanApplication loanApplication) {
        LoanBean loanBean = new LoanBean();
        BeanUtils.copyProperties(loanApplication, loanBean);
        return loanBean;
    }
    
    
    /**
     * 手机端条件查询
     * @param page
     * @param size
     * @param loanBean
     * @return
     */
	public GridData<MobileLoanBean> find4MobileByCondition(int page, int size, MobileLoanBean loanBean) {

		Pageable pageable = new PageRequest(page, size);
		Specification<LoanApplication> specification = (root, query, criteriaBuilder) -> {
			List<Predicate> predicates = new ArrayList<>();

			// 贷款类型
			if (loanBean.getPickupTimeStart() != null && !loanBean.getPickupTimeStart().equals("") &&
					loanBean.getPickupTimeEnd() != null && !loanBean.getPickupTimeEnd().equals("")) {
				Predicate pickupTime = criteriaBuilder.between(root.get("pickupTime").as(String.class), loanBean.getPickupTimeStart(), loanBean.getPickupTimeEnd());
				predicates.add(pickupTime);
			}

			// 贷款类型
			if (loanBean.getLoanType() != null && !loanBean.getLoanType().equals("")) {
				Predicate loanType = criteriaBuilder.equal(root.get("loanType").as(String.class), loanBean.getLoanType());
				predicates.add(loanType);
			}

			// 贷款ID模糊查询
			if (loanBean.getLoanId() != null && !loanBean.getLoanId().equals("")) {
				Predicate loanId = criteriaBuilder.like(root.get("loanId").as(String.class), loanBean.getLoanId() + "%");
				predicates.add(loanId);
			}

			// 处理进度条件
			if (loanBean.getProcessStat() != null && !loanBean.getProcessStat().equals("")) {
				Predicate processStat = criteriaBuilder.equal(root.get("processStat").as(String.class),
						loanBean.getProcessStat());
				predicates.add(processStat);
			}

			query.where(criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])));

			return query.getRestriction();
		};


		Page<LoanApplication> loanApplicationPage = loanApplicationDao.findAll(specification, pageable);
		List<LoanApplication> LoanApplications = loanApplicationPage.getContent();
		List<MobileLoanBean> mobiListBeans = new ArrayList<>();

		for (LoanApplication perApp : LoanApplications) {

			MobileLoanBean resultRowBean = new MobileLoanBean();

			resultRowBean.setLoanId(perApp.getLoanId());
			
			resultRowBean.setLoanIdCN("贷款申请（编号" + perApp.getLoanId() + "）");

			ObjectMapper mapper = new ObjectMapper();
			// 贷款明细对象
			LoanInfo loanInfo = null;
			try {
				loanInfo = mapper.readValue(perApp.getDetail(), LoanInfo.class);
			} catch (IOException e) {
				e.printStackTrace();
			}

			// 获取贷款类型
			String typeName = "";
			switch (loanInfo.getBusinessTypes()) {
            case "1":
                typeName = "一手房贷款";
                break;
            case "2":
                typeName = "二手房贷款";
                break;
            case "3":
                typeName = "个人消费贷款";
                break;
            case "4":
                typeName = "个人经营性贷款";
                break;
            case "5":
                typeName = "农户小额信用贷款";
                break;

			}

			StringBuilder listDetil = new StringBuilder();

			listDetil.append(typeName).append("，");

			// 获取贷款金额
			NumberFormat nf = new DecimalFormat("#,###.#### 万元");
			Double d = Double.valueOf(loanInfo.getAmount());
			String formatStr = nf.format(d);
			listDetil.append(formatStr + "，共");
			listDetil.append(loanInfo.getTerm() + "期，目前正处于");
			listDetil.append(LoanStat.Helper.findCnValue(perApp.getProcessStat()));
			listDetil.append("阶段");

			resultRowBean.setListDetil(listDetil.toString());
			mobiListBeans.add(resultRowBean);
		}
		GridData<MobileLoanBean> gridData = new GridData<>();
		gridData.setData(mobiListBeans);
		gridData.setNumber(loanApplicationPage.getTotalElements());
		gridData.setPage(loanApplicationPage.getNumber());
		gridData.setTotalPage(loanApplicationPage.getTotalPages());
		return gridData;
	}
}
